package com.ybbase.framework.service.flow.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ybbase.framework.mapper.flow.InstanceRecordMapper;
import com.ybbase.framework.mapper.flow.NodeConfigMapper;
import com.ybbase.framework.mapper.flow.NodeUsergroupMapper;
import com.ybbase.framework.model.po.flow.InstanceRecord;
import com.ybbase.framework.model.po.flow.NodeConfig;
import com.ybbase.framework.model.po.flow.NodeUsergroup;
import com.ybbase.framework.model.po.system.User;
import com.ybbase.framework.model.vo.BusinessEntityVO;
import com.ybbase.framework.service.flow.BaseFlowService;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author cg
 * @date 2019- 09-02 10:47
 * @DEC 流程基础服务类
 */
@Service
public class BaseFlowServiceImpl implements BaseFlowService {

    private static final String FLOW_PROCESS_TYPE_ACTIVE = "active";
    private static final String FLOW_PROCESS_TYPE_SUSPEND = "suspend";

    /**
     * 运行时Service
     */
    @Autowired
    private RuntimeService runtimeService;
    /**
     * 任务service
     */
    @Autowired
    private TaskService taskService;
    @Autowired
    protected ProcessEngine processEngine;
    @Autowired
    protected RepositoryService repositoryService;
    @Autowired
    protected HistoryService historyService;
    @Autowired
    protected ManagementService managementService;
    @Autowired
    protected IdentityService identityService;
    @Autowired
    protected InstanceRecordMapper instanceRecordMapper;
    @Autowired
    protected NodeUsergroupMapper taskUsergroupMapper;
    @Autowired
    protected NodeConfigMapper nodeConfigMapper;


    /**
     * 日志
     */
    protected Logger logger = LoggerFactory.getLogger(BaseFlowServiceImpl.class);
    private static final String SPLIT_SYMBOL = ",";

    /**
     * 根据类型获取当前部署了的流程
     *
     * @param category 类型
     * @return List<ProcessDefinition> 流程定义列表
     * @author cg
     * @date 2019-09-02 15:37
     */
    @Override
    public List<ProcessDefinition> getPDListByPDCategory(String category) {
        logger.info("【根据类型获取当前部署了的流程】category={}", category);
        List<ProcessDefinition> processDefinitions = new ArrayList<ProcessDefinition>();
        if (StringUtils.isBlank(category)) {
            processDefinitions = repositoryService.createProcessDefinitionQuery().list();
        } else {
            processDefinitions = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionCategory(category).list();
        }
        return processDefinitions;
    }

    /**
     * 根据流程定义ID获取
     *
     * @param processDefinitionId 流程定义ID
     * @return List<ProcessDefinition> 流程定义列表
     * @author cg
     * @date 2019-09-02 15:39
     */
    @Override
    public List<ProcessDefinition> getPDListByPDId(String processDefinitionId) {
        return repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).list();
    }

    /**
     * 根据流程定义ID启动工作流
     *
     * @param processDefinitionId 流程定义ID
     * @param querys              代办组或者待办人 格式 users:******* (条件)
     * @return String 流程实例ID
     * @author cg
     * @date 2019-09-02 15:45
     */
    @Override
    public String startActivit(String processDefinitionId, Map<String, Object> querys, User user, BusinessEntityVO businessEntityVO) {
        logger.info("【根据流程定义ID启动工作流】processDefinitionId={},users={}", processDefinitionId, querys);
        ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefinitionId, querys);
        Integer recordId = this.saveInstanceRecord(processDefinitionId, pi, user, businessEntityVO);
        if (recordId == 0) {
            return null;
        }
        return pi.getId();
    }

    /**
     * 查询流程节点的审核人和审核组信息
     *
     * @param list 流程节点和审核人对照表
     * @return
     * @author cg
     * @date 2019-09-26 19:31
     * @since 4.0
     */
    @Override
    public Map<String, Object> getTaskUserGroupQuerys(List<NodeUsergroup> list,List<String> taskCodes) {
        Map<String, Object> querys = new HashMap<>();
        for (String taskCode : taskCodes) {
            /**
             * 根据委托人属性辨识委托人为多人委托还是单人委托
             * */
            //if (StringUtils.isNotEmpty(t.getUserIds())) {
            //    List<String> userList = new ArrayList<>();
            //    if (t.getUserIds().indexOf(SPLIT_SYMBOL) != -1) {
            //        for (String id : t.getUserIds().split(SPLIT_SYMBOL)) {
            //            if(!StringUtils.isEmpty(id)){
            //                userList.add(id);
            //            }
            //        }
            //    }
            //    //querys.put(t.getTaskUserCode(), userList.size() > 0 ? userList : t.getUserIds());
            //    querys.put(t.getTaskUserCode(), userList);
            //    double f = new BigDecimal((float)1/userList.size()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            //    //querys.put(t.getTaskUserCode()+"Rate",0);
            //}
            ///**
            // * 根据委托组属性辨识委托组为多组委托还是单组委托
            // * */
            //if (StringUtils.isNotEmpty(t.getOrgIds())) {
            //    List<String> orgList = new ArrayList<>();
            //    if (t.getOrgIds().indexOf(SPLIT_SYMBOL) != -1) {
            //        for (String id : t.getOrgIds().split(SPLIT_SYMBOL)) {
            //            orgList.add(id);
            //        }
            //    }
            //    querys.put(t.getTaskOrgCode(), orgList.size() > 0 ? orgList : t.getOrgIds());
            //}
            ///**
            // * 根据备用委托人属性辨识备用委托人为多委托人还是单人委托
            // * */
            //if (StringUtils.isNotEmpty(t.getAlternativeUserIds())) {
            //    List<String> alternativeUserList = new ArrayList<>();
            //    if (t.getAlternativeUserIds().indexOf(SPLIT_SYMBOL) != -1) {
            //        for (String id : t.getAlternativeUserIds().split(SPLIT_SYMBOL)) {
            //            alternativeUserList.add(id);
            //        }
            //    }
            //    querys.put(t.getTaskAlternativeUserCode(),
            //            alternativeUserList.size() > 0 ? alternativeUserList : t.getAlternativeUserIds());
            //}
            ///**
            // * 根据备用委托组属性辨识备用委托组为多组委托还是单组委托
            // * */
            //if (StringUtils.isNotEmpty(t.getAlternativeOrgIds())) {
            //    List<String> alternativeOrgList = new ArrayList<>();
            //    if (t.getOrgIds().indexOf(SPLIT_SYMBOL) != -1) {
            //        for (String id : t.getAlternativeOrgIds().split(SPLIT_SYMBOL)) {
            //            alternativeOrgList.add(id);
            //        }
            //    }
            //    querys.put(t.getTaskAlternativeOrgCode(),
            //            alternativeOrgList.size() > 0 ? alternativeOrgList : t.getAlternativeOrgIds());
            //}
            List<String> userIds = new ArrayList<>();
            String taskUserCode = "";
            for (NodeUsergroup t : list) {
                if(t.getNodeCode().equals(taskCode)){
                    userIds.add(t.getUserIds());
                    taskUserCode = t.getTaskUserCode();
                }
            }
            querys.put(taskUserCode,userIds);
            double f = new BigDecimal((float)1/userIds.size()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            //querys.put(taskCode+"Rate",0);
        }
        return querys;
    }

    /**
     * 启动审批流程
     *
     * @param businessId   业务ID
     * @param businessName 业务Name
     * @param flowCode     流程编码
     * @param orgFlowType  组织机构流程代码
     * @param user         用户信息
     * @return
     * @author cg
     * @date 2019-09-26 19:46
     * @since 4.0
     */
    @Override
    public void startBaseFlow(String businessId, String businessName, String flowCode, String orgFlowType, User user) {
        QueryWrapper<NodeConfig> nodeConfigQueryWrapper = new QueryWrapper<NodeConfig>();
        nodeConfigQueryWrapper.lambda().eq(NodeConfig::getFlowCode, flowCode);
        List<String> listss = new ArrayList<>();
        List<NodeConfig> listStr = nodeConfigMapper.selectList(nodeConfigQueryWrapper);
        if (listStr!=null&&!listStr.isEmpty()){
            for(NodeConfig nodeConfig:listStr){
                listss.add(nodeConfig.getNodeCode());
            }
        }
        QueryWrapper<NodeUsergroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(NodeUsergroup::getFlowCode, flowCode);
        List<NodeUsergroup> list = taskUsergroupMapper.selectList(queryWrapper);
        Map<String, Object> querys = new HashMap<>();
        if (list != null && list.size() > 0) {
            querys = getTaskUserGroupQuerys(list,listss);
        }
        BusinessEntityVO businessEntityVO = new BusinessEntityVO();
        businessEntityVO.setBusinessId(businessId);
        businessEntityVO.setFlowCode(flowCode);
        businessEntityVO.setBusinessName(businessName);
        startActivit(flowCode, querys, user, businessEntityVO);
    }

    /**
     * 根据类型更新挂起状态
     *
     * @param state             类型
     * @param processInstanceId 实例编码
     * @param businessEntityVO  业务类
     * @return 1激活成功 2挂起成功
     * @author cg
     * @date 2019-09-03 17:38
     */
    @Override
    public int updateStatus(String state, String processInstanceId, BusinessEntityVO businessEntityVO) {
        int ints = 0;
        QueryWrapper<InstanceRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(InstanceRecord::getIsFinish, 0);
        if (StringUtils.isNotEmpty(processInstanceId)) {
            queryWrapper.lambda().eq(InstanceRecord::getRunProcessInstanceId,processInstanceId);
        }
        if (StringUtils.isNotEmpty(businessEntityVO.getBusinessId())) {
            queryWrapper.lambda().eq(InstanceRecord::getBusinessId,businessEntityVO.getBusinessId());
        }
        if (StringUtils.isNotEmpty(businessEntityVO.getFlowCode())) {
            queryWrapper.lambda().eq(InstanceRecord::getBusinessCode,businessEntityVO.getFlowCode());
        }
        List<InstanceRecord> instanceRecords = instanceRecordMapper.selectList(queryWrapper);
        if(instanceRecords!=null &&!instanceRecords.isEmpty()){
            if (FLOW_PROCESS_TYPE_ACTIVE.equals(state)) {
                //激活
                runtimeService.activateProcessInstanceById(processInstanceId);
                instanceRecords.get(0).setIsSuspended(0);
                instanceRecordMapper.update(instanceRecords.get(0),queryWrapper);
                ints = 1;
            } else if (FLOW_PROCESS_TYPE_SUSPEND.equals(state)) {
                //挂起
                runtimeService.suspendProcessInstanceById(processInstanceId);
                instanceRecords.get(0).setIsSuspended(1);
                instanceRecordMapper.update(instanceRecords.get(0),queryWrapper);
                ints = 2;
            }
        }
        return ints;
    }


    /**
     * 根据实例ID获取工作流所处的位置
     *
     * @param instanceId 流程实例ID
     * @return String 流程节点ID
     * @author cg
     * @date 2019-09-02 15:48
     */
    @Override
    public String getActivitiNow(String instanceId) {
        logger.info("【根据实例ID获取工作流所处的位置】instanceId={}", instanceId);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(instanceId);
        return instance.getActivityId();
    }

    /**
     * 根据实例ID验证工作流是不是已经停止
     *
     * @param instanceId 工作流id
     * @return Boolean true:已经停止,false:没有停止
     * @author cg
     * @date 2019-09-02 15:49
     */
    @Override
    public Boolean validateActiviti(String instanceId) {
        logger.info("【根据实例ID验证工作流是不是已经停止】instanceId={}", instanceId);
        ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                .processInstanceId(instanceId).singleResult();
        if (pi != null) {
            return false;
        }
        return true;
    }

    /**
     * 根据用户编码验证用户是否处于该工作流的当前任务组 group  user  assignee 都查
     *
     * @param userId 用户ID
     * @return Boolean true:处于,false:不处于
     * @author cg
     * @date 2019-09-02 15:50
     */
    @Override
    public Boolean validateUserIn(String userId) {
        logger.info("【根据用户编码验证用户是否处于该工作流的当前任务组】userId={}", userId);
        List<Task> list = getUserHaveTasks(userId);
        if (list != null && list.size() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 根据用户编码获取用户当前处于的任务集合 group  user  assignee 都查
     *
     * @param userId 用户ID
     * @return List<Task> 任务集合
     * @author cg
     * @date 2019-09-02 15:51
     */
    @Override
    public List<Task> getUserHaveTasks(String userId) {
        logger.info("【根据用户编码获取用户当前处于的任务集合】userId={}", userId);
        List<Task> list = taskService.createTaskQuery().taskCandidateGroup(userId).list();
        List<Task> listTwo = taskService.createTaskQuery().taskAssignee(userId).list();
        List<Task> listThree = taskService.createTaskQuery().taskCandidateUser(userId).list();
        //排除重复的
        for (int i = 0; i < listTwo.size(); i++) {
            if (!list.contains(listTwo.get(i))) {
                list.add(listTwo.get(i));
            }
        }
        for (Task task : listThree) {
            if (!list.contains(task)) {
                list.add(task);
            }
        }
        return list;
    }

    /**
     * 根据用户编码获取用户当前处于的任务id集合   group  user  assignee 都查
     *
     * @param userId 用户
     * @return List<String> 任务id集合
     * @author cg
     * @date 2019-09-02 15:52
     */
    @Override
    public List<String> getUserHaveTaskIds(String userId) {
        logger.info("【根据用户编码获取用户当前处于的任务id集合】userId={}", userId);
        List<Task> list = getUserHaveTasks(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : list) {
            ids.add(task.getId());
        }
        return ids;
    }

    /**
     * 根据用户编码获取用户当前处于签收人的任务集合 只查Assignee
     *
     * @param userId 用户
     * @return List<Task>任务集合
     * @author cg
     * @date 2019-09-02 15:54
     */
    @Override
    public List<Task> getUserHaveTasksAssignee(String userId) {
        logger.info("【根据用户编码获取用户当前处于签收人的任务集合】userId={}", userId);
        List<Task> listTwo = taskService.createTaskQuery().taskAssignee(userId).list();
        return listTwo;
    }

    /**
     * 根据用户编码获取当前用户处于签收人的工作流id集合 只查assignee
     *
     * @param userId 用户
     * @return List<String> 流程实例ID集合
     * @author cg
     * @date 2019-09-02 15:56
     */
    @Override
    public List<String> getUserHaveActivitiIdsAssignee(String userId) {
        logger.info("【根据用户编码获取当前用户处于签收人的工作流id集合】userId={}", userId);
        List<Task> tasks = getUserHaveTasksAssignee(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : tasks) {
            ids.add(task.getProcessInstanceId());
        }
        return ids;
    }

    /**
     * 根据用户编码获取用户当前处于签收人的任务id集合 只查Assignee
     *
     * @param userId 用户ID
     * @return List<String>任务id集合
     * @author cg
     * @date 2019-09-02 15:59
     */
    @Override
    public List<String> getUserHaveTasksIdsAssignee(String userId) {
        logger.info("【根据用户编码获取用户当前处于签收人的任务id集合】userId={}", userId);
        List<Task> list = getUserHaveTasksAssignee(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : list) {
            ids.add(task.getId());
        }
        return ids;
    }

    /**
     * 根据用户编码获取用户当前处于待办人的任务集合 只查Group
     *
     * @param userId 用户ID
     * @return List<Task>任务集合
     * @author cg
     * @date 2019-09-02 16:02
     */
    @Override
    public List<Task> getUserHaveTasksGroup(String userId) {
        logger.info("【根据用户编码获取用户当前处于待办人的任务集合】userId={}", userId);
        List<Task> list = taskService.createTaskQuery().taskCandidateGroup(userId).list();
        return list;
    }

    /**
     * 根据用户编码获取用户当前处于待办人的任务id集合 只查Group
     *
     * @param userId 用户ID
     * @return List<String>任务id集合
     * @author cg
     * @date 2019-09-02 16:03
     */
    @Override
    public List<String> getUserHaveTasksIdsGroup(String userId) {
        logger.info("【根据用户编码获取用户当前处于待办人的任务id集合】userId={}", userId);
        List<Task> list = getUserHaveTasksGroup(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : list) {
            ids.add(task.getId());
        }
        return ids;
    }

    /**
     * 根据用户编码获取当前用户处于待办人的工作流id集合 只查group
     *
     * @param userId 用户
     * @return List<String>流程实例集合
     * @author cg
     * @date 2019-09-02 16:04
     */
    @Override
    public List<String> getUserHaveActivitiIdsGroup(String userId) {
        logger.info("【根据用户编码获取当前用户处于待办人的工作流id集合】userId={}", userId);
        List<Task> tasks = getUserHaveTasksGroup(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : tasks) {
            ids.add(task.getProcessInstanceId());
        }
        return ids;
    }

    /**
     * 根据用户编码获取用户当前处于待办人的任务集合 只查user
     *
     * @param userId 用户
     * @return List<Task> 任务集合
     * @author cg
     * @date 2019-09-02 16:05
     */
    @Override
    public List<Task> getUserHaveTasksUser(String userId) {
        logger.info("【根据用户编码获取用户当前处于待办人的任务集合】userId={}", userId);
        List<Task> list = taskService.createTaskQuery().taskCandidateUser(userId).list();
        return list;
    }

    /**
     * 根据用户编码获取当前用户处于待办人的工作流id集合 只查user
     *
     * @param userId 用户ID
     * @return List<String>流程实例集合
     * @author cg
     * @date 2019-09-02 16:07
     */
    @Override
    public List<String> getUserHaveActivitiIdsUser(String userId) {
        logger.info("【根据用户编码获取当前用户处于待办人的工作流id集合】userId={}", userId);
        List<Task> tasks = getUserHaveTasksUser(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : tasks) {
            ids.add(task.getProcessInstanceId());
        }
        return ids;
    }

    /**
     * 根据用户编码获取用户当前处于待办人的任务id集合 只查Group
     *
     * @param userId 用户ID
     * @return List<String>任务id集合
     * @author cg
     * @date 2019-09-02 17:36
     */
    @Override
    public List<String> getUserHaveTasksIdsUser(String userId) {
        logger.info("【根据用户编码获取用户当前处于待办人的任务id集合】userId={}", userId);
        List<Task> list = getUserHaveTasksUser(userId);
        List<String> ids = new ArrayList<String>();
        for (Task task : list) {
            ids.add(task.getId());
        }
        return ids;
    }

    /**
     * 根据流程实例ID获取当前工作流的当前任务列表
     *
     * @param instanceId 工作流id
     * @return List<Task> 当前任务列表
     * @author cg
     * @date 2019-09-02 17:42
     */
    @Override
    public List<Task> getInstanceTasks(String instanceId) {
        logger.info("【根据流程实例ID获取当前工作流的当前任务】instanceId={}", instanceId);
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(instanceId).list();
        return tasks;
    }

    /**
     * 根据流程实例ID获取当前工作流的当前任务id集合
     *
     * @param instanceId 工作流id
     * @return List<String> 当前任务id集合
     * @author cg
     * @date 2019-09-02 17:45
     */
    @Override
    public List<String> getInstanceTaskIds(String instanceId) {
        logger.info("【根据流程实例ID获取当前工作流的当前任务id集合】instanceId={}", instanceId);
        List<Task> tasks = getInstanceTasks(instanceId);
        List<String> taskIds = new ArrayList<String>();
        for (Task task : tasks) {
            taskIds.add(task.getId());
        }
        return taskIds;
    }

    /**
     * 根据实例ID和用户编码获取当前工作流的该用户的当前任务 只查了 group 和 assignee
     *
     * @param instanceId 工作流id
     * @param userId     用户id
     * @return List<Task> 当前任务集合
     * @author cg
     * @date 2019-09-02 17:46
     */
    @Override
    public List<Task> getInstanceUserTasks(String instanceId, String userId) {
        logger.info("【获取当前工作流的该用户的当前任务】instanceId={}", instanceId);
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(instanceId)
                .taskCandidateGroup(userId).list();
        List<Task> listTwo = taskService.createTaskQuery().processInstanceId(instanceId)
                .taskAssignee(userId).list();
        //排除重复的
        for (int i = 0; i < listTwo.size(); i++) {
            if (!tasks.contains(listTwo.get(i))) {
                tasks.add(listTwo.get(i));
            }
        }
        return tasks;
    }

    /**
     * 根据实例ID和用户编码获取当前工作流的该用户的当前任务id集合 只查了 group 和 assignee
     *
     * @param instanceId 工作流id
     * @param userId     用户id
     * @return List<String>当前任务id集合
     * @author cg
     * @date 2019-09-02 17:48
     */
    @Override
    public List<String> getInstanceUserTaskIds(String instanceId, String userId) {
        logger.info("【根据实例ID和用户编码获取当前工作流的该用户的当前任务id集合】instanceId={}", instanceId);
        List<Task> tasks = getInstanceUserTasks(instanceId, userId);
        List<String> taskIds = new ArrayList<String>();
        for (Task task : tasks) {
            taskIds.add(task.getId());
        }
        return taskIds;
    }

    /**
     * 获取当前工作流的该用户的当前任务id集合  查了 group 和 assignee user
     *
     * @param instanceId 工作流id
     * @param userId     用户id
     * @param role       角色或者 继续放入 userId
     * @return List<String> 当前任务id集合
     * @author cg
     * @date 2019-09-02 17:49
     */
    @Override
    public List<String> getInstanceUserTaskIds(String instanceId, String userId, String role) {
        logger.info("【获取工作流的当前任务的当前任务id集合】instanceId={}", instanceId);
        List<Task> tasks = getInstanceUserTasks(instanceId, userId, role);
        List<String> taskIds = new ArrayList<String>();
        for (Task task : tasks) {
            taskIds.add(task.getId());
        }
        return taskIds;
    }

    /**
     * 根据工作流id、用户id、角色编码（或者 继续放入 userId）获取当前工作流的该用户的当前任务 查了 group 和 assignee user
     *
     * @param instanceId 工作流id
     * @param userId     用户id
     * @param role       角色或者 继续放入 userId
     * @return List<Task> 当前任务集合
     * @author cg
     * @date 2019-09-02 17:50
     */
    @Override
    public List<Task> getInstanceUserTasks(String instanceId, String userId, String role) {
        logger.info("【获取当前工作流的该用户的当前任务】instanceId={}", instanceId);
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(instanceId)
                .taskCandidateGroup(userId).list();
        List<Task> listTwo = taskService.createTaskQuery().processInstanceId(instanceId)
                .taskAssignee(userId).list();
        List<Task> listThree = taskService.createTaskQuery().processInstanceId(instanceId)
                .taskCandidateUser(role).list();
        //排除重复的
        for (Task task : listThree) {
            if (!tasks.contains(task)) {
                tasks.add(task);
            }
        }
        for (Task task : listTwo) {
            if (!tasks.contains(task)) {
                tasks.add(task);
            }
        }
        return tasks;
    }

    /**
     * 获取工作流的当前任务的用户组  group user assignee
     *
     * @param instanceId 工作流实例id
     * @return Map<String, List < String>> key:taskId,value:用户集合
     * @author cg
     * @date 2019-09-02 17:52
     */
    @Override
    public Map<String, List<String>> getUserIdsMap(String instanceId) {
        logger.info("【获取工作流的当前任务的用户组】instanceId={}", instanceId);
        List<Task> tasks = getInstanceTasks(instanceId);
        Map<String, List<String>> userIdsAll = new HashMap<String, List<String>>();
        for (Task task : tasks) {
            logger.info("【当前任务id】taskId={}", task.getName());
            List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
            List<String> userIds = new ArrayList<String>();
            String userId = "";
            if (StringUtils.isNotBlank(task.getAssignee())) {
                userIds.add(task.getAssignee());
            }
            for (IdentityLink identityLink : identityLinks) {
                //获取用户封装入list
                userId = identityLink.getGroupId();
                if (StringUtils.isBlank(userId)) {
                    //group中无用户
                    userId = identityLink.getUserId();
                    if (StringUtils.isBlank(userId)) {
                        //group中无用户和userId中无用户
                        continue;
                    }
                }
                if (userIds.contains(userId)) {
                    continue;
                }
                userIds.add(userId);
            }
            //加入返回 key:taskId,value:用户集合
            userIdsAll.put(task.getId(), userIds);
        }
        return userIdsAll;
    }

    /**
     * 流程实例ID获取用户所处的任务id集合 根据groupId查找
     *
     * @param instanceId 流程实例ID
     * @param userId     用户组ID
     * @return List<String> 任务id集合
     * @author cg
     * @date 2019-09-02 17:54
     */
    @Override
    public List<String> getInstanceGroupTaskIds(String instanceId, String userId) {
        List<String> taskIds = new ArrayList<String>();
        List<Task> tasks = getInstanceTasks(instanceId);
        for (Task task : tasks) {
            if (StringUtils.isNotBlank(task.getAssignee())) {
                continue;
            }
            List<String> userIds = getGroupUserIds(task);
            if (userIds.contains(userId)) {
                taskIds.add(task.getId());
            }
        }
        return taskIds;
    }

    /**
     * 获取用户所处的任务id集合 根据userId查找
     *
     * @param instanceId 实例ID
     * @param userId     用户ID
     * @return List<String> 任务id集合
     * @author cg
     * @date 2019-09-02 18:08
     */
    @Override
    public List<String> getInstanceUsersTaskIds(String instanceId, String userId) {
        List<String> taskIds = new ArrayList<String>();
        List<Task> tasks = getInstanceTasks(instanceId);
        for (Task task : tasks) {
            if (StringUtils.isNotBlank(task.getAssignee())) {
                continue;
            }
            List<String> userIds = getUserUserIds(task);
            if (userIds.contains(userId)) {
                taskIds.add(task.getId());
            }
        }
        return taskIds;
    }

    /**
     * 获取用户所处的任务id集合 根据Assignee查找
     *
     * @param instanceId 流程实例编码
     * @param userId     Assignee用户编码
     * @return List<String>任务id集合
     * @author cg
     * @date 2019-09-02 18:27
     */
    @Override
    public List<String> getInstanceAssigneeTaskIds(String instanceId, String userId) {
        List<String> taskIds = new ArrayList<String>();
        List<Task> tasks = getInstanceTasks(instanceId);
        for (Task task : tasks) {
            String userIds = getAssigneeUserIds(task);
            if (userId.equals(userIds)) {
                taskIds.add(task.getId());
            }
        }
        return taskIds;
    }

    /**
     * 根据工作流实例id获取工作流的当前任务的所有用户组 groupId  userId  assignee
     *
     * @param instanceId 工作流实例id
     * @return List<List < String>> 表示当前任务可能不只有一个
     * @author cg
     * @date 2019-09-02 18:28
     */
    @Override
    public List<List<String>> getUserIds(String instanceId) {
        logger.info("【获取工作流的当前任务的用户组】instanceId={}", instanceId);
        List<Task> tasks = getInstanceTasks(instanceId);
        List<List<String>> userIdsAll = new ArrayList<List<String>>();
        for (Task task : tasks) {
            logger.info("【当前任务id】taskId={}", task.getName());
            List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
            List<String> userIds = new ArrayList<String>();
            String userId = "";
            String groupId = "";
            if (StringUtils.isNotBlank(task.getAssignee())) {
                userIds.add(task.getAssignee());
                logger.info("【有签收人不用再获取用户】");
                continue;
            }
            for (IdentityLink identityLink : identityLinks) {
                //获取用户封装入list
                groupId = identityLink.getGroupId();
                if (StringUtils.isNotBlank(groupId)) {
                    if (groupId.indexOf(",") > 0) {
                        String[] idStr = groupId.split(",");
                        for (String idOne : idStr) {
                            if (!userIds.contains(idOne)) {
                                userIds.add(idOne);
                            }
                        }
                    }
                }
                if (groupId.length() == 1) {
                    if (!userIds.contains(groupId)) {
                        userIds.add(groupId);
                    }
                }
                userId = identityLink.getUserId();
                if (StringUtils.isNotBlank(userId)) {
                    if (userId.indexOf(",") > 0) {
                        String[] idStr = userId.split(",");
                        for (String idOne : idStr) {
                            if (!userIds.contains(idOne)) {
                                userIds.add(idOne);
                            }
                        }
                    }
                }
                if (userId.length() == 1) {
                    if (!userIds.contains(userId)) {
                        userIds.add(userId);
                    }
                }
            }
            //加入返回List<List<String>>
            userIdsAll.add(userIds);
        }
        return userIdsAll;
    }

    /**
     * 根据流程实例编码获取工作流的当前任务的所有用户组 groupId  userId  assignee
     *
     * @param instanceId 工作流实例id
     * @return List<String>当前任务的所有用户组
     * @author cg
     * @date 2019-09-02 18:30
     */
    @Override
    public List<String> getUserIdsOneList(String instanceId) {
        List<List<String>> lists = getUserIds(instanceId);
        List<String> ids = new ArrayList<String>();
        for (List<String> list : lists) {
            for (String id : list) {
                if (!ids.contains(id)) {
                    ids.add(id);
                }
            }
        }
        return ids;
    }

    /**
     * 根据taskId进行完成任务
     *
     * @param taskId 任务id
     * @author cg
     * @date 2019-09-02 18:31
     */
    @Override
    public void completeTask(String taskId) {
        logger.info("【完成任务】taskId={}", taskId);
        taskService.complete(taskId);
    }

    /**
     * 根据任务编码和用户编码完成任务
     *
     * @param taskId 任务id
     * @param userId 用户id
     * @author cg
     * @date 2019-09-02 18:31
     */
    @Override
    public void completeTask(String taskId, String userId) {
        logger.info("【完成任务】taskId={},userId={}", taskId, userId);
        taskService.complete(taskId);
    }

    /**
     * 根据任务编码和用户编码认领任务
     *
     * @param taskId 任务id
     * @param userId 用户id
     * @author cg
     * @date 2019-09-02 18:32
     */
    @Override
    public void claimTask(String taskId, String userId) {
        taskService.claim(taskId, userId);
    }

    /**
     * 根据流程实例编码查询是否结束
     *
     * @param instanceId 流程实例id
     * @return Boolean true流程实例结束了 false 实例未结束了
     * @author cg
     * @date 2019-09-02 18:33
     */
    @Override
    public Boolean validateEnd(String instanceId) {
        //创建流程实例查询对象
        ProcessInstance rpi = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processInstanceId(instanceId).singleResult();
        //说明流程实例结束了
        if (rpi == null) {
            return true;
        }
        return false;
    }

    /**
     * 获取用户id集合
     *
     * @param nameIds 切串用户编码集
     * @return List<String> 用户编码
     * @author cg
     * @date 2019-09-02 18:35
     */
    @Override
    public List<String> analysisUserId(String nameIds) {
        List<String> ids = new ArrayList<String>();
        while (nameIds.lastIndexOf("),") > 0) {
            int startIndex = nameIds.indexOf("(");
            int endIndex = nameIds.indexOf("),");
            String id = nameIds.substring(startIndex + 1, endIndex);
            ids.add(id);
            nameIds = nameIds.substring(endIndex + 2);
        }
        return ids;
    }


    /**
     * 修改变量
     *
     * @param activitiId 工作流id
     * @param variables  条件
     * @author cg
     * @date 2019-09-02 18:37
     */
    @Override
    public void setVar(String activitiId, Map<String, Object> variables) {
        logger.info("【修改变量】activitiId={},variables={}", activitiId, variables);
        List<Task> tasks = getInstanceTasks(activitiId);
        for (Task task : tasks) {
            taskService.setVariables(task.getId(), variables);
        }
    }

    /**
     * 获取工作流的当前任务的groupId用户组
     *
     * @param instanceId 工作流实例id
     * @return List<List < String>> 表示当前任务可能不只有一个
     * @author cg
     * @date 2019-09-02 18:37
     */
    @Override
    public List<List<String>> getGroupUserIds(String instanceId) {
        logger.info("【获取工作流的当前任务的用户组】instanceId={}", instanceId);
        List<Task> tasks = getInstanceTasks(instanceId);
        List<List<String>> userIdsAll = new ArrayList<List<String>>();
        for (Task task : tasks) {
            logger.info("【当前任务id】taskId={}", task.getName());
            List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
            List<String> userIds = new ArrayList<String>();
            String userId = "";
            if (StringUtils.isNotBlank(task.getAssignee())) {
                logger.info("【有签收人 不用获取用户】");
                continue;
            }
            for (IdentityLink identityLink : identityLinks) {
                //获取用户封装入list
                userId = identityLink.getGroupId();
                if (StringUtils.isBlank(userId)) {
                    //group中无用户
                    continue;
                }
                if (userId.indexOf(",") > 0) {
                    String[] idStr = userId.split(",");
                    for (String idOne : idStr) {
                        if (!userIds.contains(idOne)) {
                            userIds.add(idOne);
                        }
                    }
                }
                if (userId.length() == 1) {
                    if (!userIds.contains(userId)) {
                        userIds.add(userId);
                    }
                }
            }
            //加入返回List<List<String>>
            userIdsAll.add(userIds);
        }
        return userIdsAll;
    }

    /**
     * 获取工作流的当前任务的groupId用户组
     *
     * @param instanceId 工作流实例id
     * @return List<String> groupId用户组
     * @author cg
     * @date 2019-09-02 18:38
     */
    @Override
    public List<String> getGroupUserIdsOneList(String instanceId) {
        List<List<String>> lists = getGroupUserIds(instanceId);
        List<String> ids = new ArrayList<String>();
        for (List<String> list : lists) {
            for (String id : list) {
                if (!ids.contains(id)) {
                    ids.add(id);
                }
            }
        }
        return ids;
    }

    /**
     * 获取工作流的当前任务的userId用户组
     *
     * @param instanceId 工作流实例id
     * @return List<List < String>> 表示当前任务可能不只有一个
     * @author cg
     * @date 2019-09-02 18:50
     */
    @Override
    public List<List<String>> getUserUserIds(String instanceId) {
        logger.info("【获取工作流的当前任务的用户组】instanceId={}", instanceId);
        List<Task> tasks = getInstanceTasks(instanceId);
        List<List<String>> userIdsAll = new ArrayList<List<String>>();
        for (Task task : tasks) {
            logger.info("【当前任务id】taskId={}", task.getName());
            List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
            List<String> userIds = new ArrayList<String>();
            String userId = "";
            if (StringUtils.isNotBlank(task.getAssignee())) {
                logger.info("【有签收人 不用获取用户】");
                continue;
            }
            for (IdentityLink identityLink : identityLinks) {
                userId = identityLink.getUserId();
                if (StringUtils.isBlank(userId)) {
                    continue;
                }
                if (userId.indexOf(",") > 0) {
                    String[] idStr = userId.split(",");
                    for (String idOne : idStr) {
                        if (!userIds.contains(idOne)) {
                            userIds.add(idOne);
                        }
                    }
                }
                if (userId.length() == 1) {
                    if (!userIds.contains(userId)) {
                        userIds.add(userId);
                    }
                }
            }
            //加入返回List<List<String>>
            userIdsAll.add(userIds);
        }
        return userIdsAll;
    }

    /**
     * 根据工作流实例id获取工作流的当前任务的userId用户组
     *
     * @param instanceId 工作流实例id
     * @return List<String> userId用户组
     * @author cg
     * @date 2019-09-02 18:51
     */
    @Override
    public List<String> getUserUserIdsOneList(String instanceId) {
        List<List<String>> lists = getUserUserIds(instanceId);
        List<String> ids = new ArrayList<String>();
        for (List<String> list : lists) {
            for (String id : list) {
                if (!ids.contains(id)) {
                    ids.add(id);
                }
            }
        }
        return ids;
    }

    /**
     * 根据任务task获取工作流的当前任务的groupId用户组
     *
     * @param task 工作流任务实体
     * @return List<String>groupId用户组
     * @author cg
     * @date 2019-09-02 18:52
     */
    @Override
    public List<String> getGroupUserIds(Task task) {
        logger.info("【当前任务id】taskId={}", task.getName());
        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
        List<String> userIds = new ArrayList<String>();
        String userId = "";
        if (StringUtils.isNotBlank(task.getAssignee())) {
            logger.info("【有签收人 不用获取用户】");
            return userIds;
        }
        for (IdentityLink identityLink : identityLinks) {
            //获取用户封装入list
            userId = identityLink.getGroupId();
            if (StringUtils.isBlank(userId)) {
                //group中无用户
                continue;
            }
            if (userId.indexOf(",") > 0) {
                String[] idStr = userId.split(",");
                for (String idOne : idStr) {
                    if (!userIds.contains(idOne)) {
                        userIds.add(idOne);
                    }
                }
            }
            if (userId.length() == 1) {
                if (!userIds.contains(userId)) {
                    userIds.add(userId);
                }
            }
        }
        //加入返回List<List<String>>
        return userIds;
    }

    /**
     * 根据任务task获取工作流的当前任务的userId用户组
     *
     * @param task 工作流任务实体
     * @return List<List < String>> 表示当前任务可能不只有一个
     * @author cg
     * @date 2019-09-02 18:53
     */
    @Override
    public List<String> getUserUserIds(Task task) {
        logger.info("【当前任务id】taskId={}", task.getName());
        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
        List<String> userIds = new ArrayList<String>();
        String userId = "";
        if (StringUtils.isNotBlank(task.getAssignee())) {
            logger.info("【有签收人 不用获取用户】");
            return userIds;
        }
        for (IdentityLink identityLink : identityLinks) {
            userId = identityLink.getUserId();
            if (StringUtils.isBlank(userId)) {
                continue;
            }
            if (userId.indexOf(",") > 0) {
                String[] idStr = userId.split(",");
                for (String idOne : idStr) {
                    if (!userIds.contains(idOne)) {
                        userIds.add(idOne);
                    }
                }
            }
            if (userId.length() == 1) {
                if (!userIds.contains(userId)) {
                    userIds.add(userId);
                }
            }
        }
        return userIds;
    }

    /**
     * 根据流程实例ID获取工作流的当前任务的assignee用户组
     *
     * @param instanceId 工作流实例id
     * @return List<String> 当前任务的assignee用户组
     * @author cg
     * @date 2019-09-02 18:54
     */
    @Override
    public List<String> getAssigneeUserIds(String instanceId) {
        logger.info("【获取工作流的当前任务的用户组】instanceId={}", instanceId);
        List<Task> tasks = getInstanceTasks(instanceId);
        List<String> userIds = new ArrayList<String>();
        for (Task task : tasks) {
            logger.info("【当前任务id】taskId={}", task.getName());
            String userId = "";
            if (StringUtils.isNotBlank(task.getAssignee())) {
                userId = task.getAssignee();
                if (StringUtils.isBlank(userId)) {
                    continue;
                }
                if (userIds.contains(userId)) {
                    continue;
                }
                userIds.add(userId);
            }
        }
        return userIds;
    }

    /**
     * 根据流程任务实体获取工作流的当前任务的assignee用户组
     *
     * @param task 工作流任务实体
     * @return List<List < String>> assignee用户组表示当前任务可能不只有一个
     * @author cg
     * @date 2019-09-02 18:56
     */
    @Override
    public String getAssigneeUserIds(Task task) {
        logger.info("【当前任务id】taskId={}", task.getName());
        String userId = "";
        if (StringUtils.isNotBlank(task.getAssignee())) {
            userId = task.getAssignee();
            if (StringUtils.isBlank(userId)) {
                return null;
            }
        }
        return userId;
    }

    /**
     * 设置组用户 放入groupId中
     *
     * @param ids  用户编码集
     * @param task 工作流任务实体
     * @author cg
     * @date 2019-09-02 19:10
     */
    @Override
    public void addGroupIds(List<String> ids, Task task) {
        String idStr = "";
        for (String id : ids) {
            idStr += id + ",";
        }
        taskService.addCandidateGroup(task.getId(), idStr);
    }

    /**
     * 已办获取历史任务 查询用户处于签收人 assignee
     *
     * @param userId 用户编码
     * @return List<HistoricTaskInstance> 历史实例编码
     * @author cg
     * @date 2019-09-02 19:20
     */
    @Override
    public List<HistoricTaskInstance> getHistoryAssigneeActivitiIds(String userId) {
        // 历史任务Service
        List<HistoricTaskInstance> list = processEngine.getHistoryService()
                // 创建历史任务实例查询
                .createHistoricTaskInstanceQuery()
                // 指定办理人
                .taskAssignee(userId)
                // 查询已经完成的任务
                .finished()
                .list();
        return list;
    }

    /**
     * 获取历史任务 查询用户处于签收人 assignee
     *
     * @param userId 用户编码
     * @return List<String> 历史签收的流程实例编码集
     * @author cg
     * @date 2019-09-02 19:21
     */
    @Override
    public List<String> getHistoryAssigneeActivitiIdsString(String userId) {
        List<HistoricTaskInstance> list = getHistoryAssigneeActivitiIds(userId);
        List<String> ids = new ArrayList<String>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            if (!ids.contains(historicTaskInstance.getProcessInstanceId())) {
                ids.add(historicTaskInstance.getProcessInstanceId());
            }
        }
        return ids;
    }

    /**
     * 获取历史任务 查询用户处于已办组 group
     *
     * @param userId 用户组编码
     * @return List<HistoricTaskInstance> 历史实例编码集
     * @author cg
     * @date 2019-09-02 19:24
     */
    @Override
    public List<HistoricTaskInstance> getHistoryGroupActivitiIds(String userId) {
        // 历史任务Service
        List<HistoricTaskInstance> list = processEngine.getHistoryService()
                // 创建历史任务实例查询
                .createHistoricTaskInstanceQuery()
                // 查询已经完成的任务
                .taskCandidateGroup(userId).finished()
                .list();
        return list;
    }

    /**
     * 获取历史任务 查询用户处于代办组 group
     *
     * @param userId 用户组编码
     * @return List<String> 历史签收的流程实例编码集
     * @author cg
     * @date 2019-09-02 19:25
     */
    @Override
    public List<String> getHistoryGroupActivitiIdsString(String userId) {
        List<HistoricTaskInstance> list = getHistoryGroupActivitiIds(userId);
        List<String> ids = new ArrayList<String>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            if (!ids.contains(historicTaskInstance.getProcessInstanceId())) {
                ids.add(historicTaskInstance.getProcessInstanceId());
            }
        }
        return ids;
    }

    /**
     * 获取历史流程实例 查询用户处于已办组 group
     *
     * @param userId 用户组编码
     * @return List<HistoricTaskInstance> 历史流程实例集
     * @author cg
     * @date 2019-09-02 19:26
     */
    @Override
    public List<HistoricTaskInstance> getHistoryUserActivitiIds(String userId) {
        // 历史任务Service
        List<HistoricTaskInstance> list = processEngine.getHistoryService()
                // 创建历史任务实例查询
                .createHistoricTaskInstanceQuery()
                // 查询已经完成的任务
                .taskCandidateUser(userId).finished()
                .list();
        return list;
    }

    /**
     * 获取历史任务 查询用户处于已办组 group
     *
     * @param userId 用户组编码
     * @return List<String> 历史流程实例ID集
     * @author cg
     * @date 2019-09-02 19:28
     */
    @Override
    public List<String> getHistoryUserActivitiIdsString(String userId) {
        List<HistoricTaskInstance> list = getHistoryUserActivitiIds(userId);
        List<String> ids = new ArrayList<String>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            if (!ids.contains(historicTaskInstance.getProcessInstanceId())) {
                ids.add(historicTaskInstance.getProcessInstanceId());
            }
        }
        return ids;
    }

    /**
     * 根据流程代码和业务ID获取当前审核人ID
     *
     * @param flowCode 流程代码
     * @param businessId   业务ID
     * @return String
     * @author cg
     * @date 2019-11-12 11:11
     * @since 4.0
     */
    @Override
    public String getFlowTaskAssignee(String flowCode, String businessId) {
        QueryWrapper<InstanceRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(InstanceRecord::getIsFinish, 0);
        queryWrapper.lambda().eq(InstanceRecord::getBusinessCode, flowCode);
        queryWrapper.lambda().eq(InstanceRecord::getBusinessId, businessId);
        InstanceRecord in = instanceRecordMapper.selectOne(queryWrapper);
        if (in != null) {
            Task task = taskService.createTaskQuery().processInstanceId(in.getRunProcessInstanceId()).active().singleResult();
            return task.getAssignee();
        }
        return null;
    }

    /**
     * 保存流程实例记录
     *
     * @param processDefinitionId 流程定义ID
     * @param processInstance     流程实例实体
     * @param user                用户实体
     * @param businessEntityVO    业务类型实体
     * @return 流程实例记录的Id
     * @author cg
     * @date 2019-09-03 15:04
     */
    public Integer saveInstanceRecord(String processDefinitionId, ProcessInstance processInstance, User user, BusinessEntityVO businessEntityVO) {
        InstanceRecord instanceRecord = new InstanceRecord();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
        if (processDefinition != null) {
            Model model = repositoryService.createModelQuery().deploymentId(processDefinition.getDeploymentId()).singleResult();
            instanceRecord.setModelId(model.getId());
            instanceRecord.setRunDefinitionId(processDefinitionId);
            instanceRecord.setRunProcessInstanceId(processInstance.getId());
            instanceRecord.setUserId(user.getId());
            instanceRecord.setUserName(user.getName());
            instanceRecord.setBusinessCode(businessEntityVO.getFlowCode());
            instanceRecord.setBusinessId(businessEntityVO.getBusinessId());
            instanceRecord.setBusinessName(businessEntityVO.getBusinessName());
            instanceRecord.setOrganId(user.getDefaultOrgId());
            instanceRecord.setOrganName(user.getDefaultOrgName());
            instanceRecord.setVersion(model.getVersion());
            // todo tableName
            instanceRecordMapper.insert(instanceRecord);
            return instanceRecord.getId();
        }
        return 0;
    }

    /**
     * 根据当前登录用户的Id和业务编码获取业务编码集合
     * @param
     * @return
     * @author cg
     * @date 2019-12-17 21:36
     * @since cloud2.0
    */
    @Override
    public List<Integer> getBusinessId(String businessCode, String userId) {
        String[] ss = instanceRecordMapper.getBusinessId(businessCode, userId);
        List<Integer> list = new ArrayList<>();
        if (ss!=null && ss.length>0){
            for (String s:ss){
                if (StringUtils.isNotEmpty(s)&&!"null".equals(s)){
                    list.add(Integer.parseInt(s));
                }
            }
        }
        return  list;
    }
}
